package com.rolerealm.service.impl;

import com.rolerealm.service.LLMService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.Duration;

/**
 * 文心一言（ERNIE） LLM 实现
 */
@Slf4j
@Service
public class WenxinLLMServiceImpl implements LLMService {

    @Value("${llm.wenxin.ak:}")
    private String ak;

    @Value("${llm.wenxin.sk:}")
    private String sk;

    @Value("${llm.wenxin.accessToken:}")
    private String presetAccessToken;

    @Value("${llm.wenxin.model:completions_pro}")
    private String modelPath; // completions, completions_pro, turbo 等

    private volatile String cachedToken;
    private volatile long tokenExpireAt = 0L;

    private final HttpClient httpClient = HttpClient.newBuilder()
            .connectTimeout(Duration.ofSeconds(10))
            .build();

    @Override
    public String infer(String prompt, String languageOrModel) {
        try {
            String token = getAccessToken();
            if (token == null || token.isBlank()) {
                log.warn("Wenxin accessToken 不可用，回退回声");
                return "AI回复：" + (prompt == null ? "" : prompt);
            }

            String url = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/" + modelPath + "?access_token=" + token;
            String body = "{\n" +
                    "  \"messages\": [\n" +
                    "    {\"role\": \"user\", \"content\": " + toJsonString(prompt) + "}\n" +
                    "  ]\n" +
                    "}";

            HttpRequest request = HttpRequest.newBuilder()
                    .uri(URI.create(url))
                    .timeout(Duration.ofSeconds(30))
                    .header("Content-Type", "application/json")
                    .POST(HttpRequest.BodyPublishers.ofString(body, StandardCharsets.UTF_8))
                    .build();

            HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8));
            if (response.statusCode() / 100 != 2) {
                log.error("Wenxin API 调用失败，status={} body={}", response.statusCode(), response.body());
                return fallback(prompt);
            }

            String resp = response.body();
            String result = extractResult(resp);
            return result != null && !result.isBlank() ? result : fallback(prompt);
        } catch (Exception e) {
            log.error("调用文心一言失败", e);
            return fallback(prompt);
        }
    }

    private String fallback(String prompt) {
        return "AI回复：" + (prompt == null ? "" : prompt);
    }

    private static String toJsonString(String text) {
        if (text == null) return "\"\"";
        String esc = text.replace("\\", "\\\\").replace("\"", "\\\"").replace("\n", "\\n");
        return "\"" + esc + "\"";
    }

    // 轻量提取 result 字段
    private static String extractResult(String json) {
        if (json == null) return null;
        int idx = json.indexOf("\"result\"");
        if (idx < 0) return null;
        int colon = json.indexOf(':', idx);
        if (colon < 0) return null;
        int start = json.indexOf('"', colon + 1);
        if (start < 0) return null;
        StringBuilder sb = new StringBuilder();
        boolean escape = false;
        for (int i = start + 1; i < json.length(); i++) {
            char ch = json.charAt(i);
            if (escape) {
                switch (ch) {
                    case 'n': sb.append('\n'); break;
                    case 'r': sb.append('\r'); break;
                    case 't': sb.append('\t'); break;
                    case '"': sb.append('"'); break;
                    case '\\': sb.append('\\'); break;
                    default: sb.append(ch); break;
                }
                escape = false;
            } else {
                if (ch == '\\') { escape = true; continue; }
                if (ch == '"') break;
                sb.append(ch);
            }
        }
        return sb.toString();
    }

    private String getAccessToken() {
        if (presetAccessToken != null && !presetAccessToken.isBlank()) {
            return presetAccessToken;
        }
        long now = System.currentTimeMillis();
        if (cachedToken != null && now < tokenExpireAt) {
            return cachedToken;
        }
        if (ak == null || ak.isBlank() || sk == null || sk.isBlank()) {
            return null;
        }
        try {
            String url = "https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=" + ak + "&client_secret=" + sk;
            HttpRequest req = HttpRequest.newBuilder()
                    .uri(URI.create(url))
                    .timeout(Duration.ofSeconds(10))
                    .GET().build();
            HttpResponse<String> resp = httpClient.send(req, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8));
            if (resp.statusCode() / 100 != 2) {
                log.error("获取文心 access_token 失败，status={}, body={}", resp.statusCode(), resp.body());
                return null;
            }
            // 简单解析 access_token 和 expires_in
            String body = resp.body();
            String token = extractField(body, "access_token");
            String expiresStr = extractField(body, "expires_in");
            long expiresSec = 3600L;
            try { if (expiresStr != null) expiresSec = Long.parseLong(expiresStr); } catch (Exception ignore) {}
            if (token != null) {
                cachedToken = token;
                tokenExpireAt = System.currentTimeMillis() + (expiresSec - 60) * 1000L; // 提前1分钟过期
            }
            return cachedToken;
        } catch (Exception e) {
            log.error("获取文心 access_token 异常", e);
            return null;
        }
    }

    private static String extractField(String json, String field) {
        int idx = json.indexOf('"' + field + '"');
        if (idx < 0) return null;
        int colon = json.indexOf(':', idx);
        if (colon < 0) return null;
        int startQuote = json.indexOf('"', colon + 1);
        if (startQuote > 0) {
            // 字符串值
            int end = json.indexOf('"', startQuote + 1);
            if (end > startQuote) return json.substring(startQuote + 1, end);
        } else {
            // 数字值
            int start = colon + 1;
            int end = start;
            while (end < json.length() && Character.isDigit(json.charAt(end))) end++;
            return json.substring(start, end).trim();
        }
        return null;
    }
}


